using System;
using System.Collections.Generic;

namespace Granite.Data
{
    /// <summary>
    /// Represents any subclass of Connection that supports transactions
    /// </summary>
    public interface ITransactionalConnection : IDisposable
    {
        /// <summary>
        /// Commits the current transaction and closes the associated connection.
        /// </summary>
        void Commit();

        /// <summary>
        /// Rollsback the pennding transaction
        /// </summary>
        void Rollback();

        /// <summary>
        /// Raised when a procedure call fails.
        /// </summary>
        event EventHandler<ProcedureCallEventArgs> ProcedureCallError;
        /// <summary>
        /// Raised when a procedure call is successfully completed
        /// </summary>
        event EventHandler<ProcedureCallEventArgs> ProcedureCallFinished;
        /// <summary>
        /// Raised when a procedure call is started
        /// </summary>
        event EventHandler<ProcedureCallEventArgs> ProcedureCallStarted;
        /// <summary>
        /// Executes the procedure, returning a single non-null value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        bool ExecuteBoolean(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single non-null value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        DateTime ExecuteDateTime(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single non-null value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        decimal ExecuteDecimal(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single non-null value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        short ExecuteInt16(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single non-null value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        int ExecuteInt32(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, discarding any results
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        void ExecuteNonQuery(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single row.
        /// </summary>
        /// <param name="procedure"></param>
        /// <param name="options">Controls what happens if the wrong number of rows is returned</param>
        /// <returns></returns>
        IDictionary<string, object> ExecuteRow(ProcedureCall procedure, ExecuteRowOptions options);
        /// <summary>
        /// Executes the procedure, returning a single row.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        IDictionary<string, object> ExecuteRow(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single nullable value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        T? ExecuteScalar<T>(ProcedureCall procedure)
                where T : struct;
        /// <summary>
        /// Executes the procedure, returning a single nullable value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        string ExecuteString(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single Table.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        Table ExecuteTable(ProcedureCall procedure);
        /// <summary>
        /// Executes the procedure, returning a single non-null value.
        /// </summary>
        /// <param name="procedure"></param>
        /// <returns></returns>
        TimeSpan ExecuteTimeSpan(ProcedureCall procedure);
    }
}
